package com.the9.C9Alarm;

import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

import mainView.Graphics;

import com.the9.C9Alarm.R;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.RectF;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.PorterDuffXfermode;
import android.graphics.Typeface;
import android.graphics.Xfermode;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class CenterCirView extends SurfaceView implements
		SurfaceHolder.Callback, Runnable, OnChangeAlarmListener {

	private int color_alarm_off = Color.GRAY;
	private int color_alarm_on = Color.RED | Color.GRAY;
	private int color_alarm_special = Color.RED;

	private Bitmap Bitmap_time = null;
	private int I_cirAniCount = 0;
	private Bitmap[] Bitmap_cirAnim = null;
	private Bitmap Bitmap_cirArrow = null,Bitmap_cirBg=null;
	private int cirAnimFps;
	private int cirAnimSpeed;
	private int SLEEPTIME = 0;
	int width, height;
	SurfaceHolder mSurfaceHolder;
	Boolean mLoop;
	Paint arcPaint, textPaint;
	private Graphics mG = new Graphics();
	PaintFlagsDrawFilter mSetfil;
	Timer DayChangeTimer;
	private Object inialOver;
	private float pspeed_abs = 0;
	private int vibarate_count = 0;
	private int vibarate_Max = 1;
	int lastCircleAnimIndex;
	boolean efficentMode = false;

	public CenterCirView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		Log.e("boxGameView", "boxGameView");
		mSurfaceHolder = this.getHolder();

		mSurfaceHolder.addCallback(this);

		this.setZOrderOnTop(true);
		// this.setEGLConfigChooser(8, 8, 8, 8, 16, 0); 0Wm-` ZA
		this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
		mSetfil = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG);
		currentAngle = 0;
		alarmState = ALARMSTATE_NOALARM;

	}

	@Override
	public void run() {
		Log.e("boxGameView", "thread start");
		Canvas c = null;

		int dayFromZero = (int) (System.currentTimeMillis() / Symbol.INTERVAL_DAY);
		// DayChangeTimer.schedule(task, new
		// Date((dayFromZero+1)*Symbol.INTERVAL_DAY),Symbol.INTERVAL_DAY);

		while (mLoop) {
			synchronized (mSurfaceHolder) {

				updateLogic();
				c = mSurfaceHolder.lockCanvas();
				try {
					mG.setCanvas(c);
					if (!efficentMode || state != STATE_CHANGEING) {
						drawNewPage(mG);
					}
					switch (state) {
					case STATE_CHANGEING:
						drawChangeing(mG);
						break;
					case STATE_DONE:
						drawDone(mG);
						break;
					}
					mSurfaceHolder.unlockCanvasAndPost(c);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {

				}

				if (state == STATE_DONE) {
					try {
						do {
							mSurfaceHolder.wait();
						} while (inialOver == null);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}

			}
			try {
				Thread.sleep(SLEEPTIME);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}
		Log.e("boxGameView", "thread over");
	}

	private String translateTimeToString(Long time) {
		Calendar cltime = Calendar.getInstance();
		cltime.setTimeInMillis(time);

		time += (long) cltime.get(Calendar.ZONE_OFFSET);//
		Long currtentTime = System.currentTimeMillis()
				+ (long) cltime.get(Calendar.ZONE_OFFSET);
		int dayFromZero = (int) (currtentTime / Symbol.INTERVAL_DAY);
		Log.e("aaaaaa", "time:" + time + ":" + time / Symbol.INTERVAL_DAY
				+ " current:" + currtentTime + ":" + currtentTime
				/ Symbol.INTERVAL_DAY);
		int day = (int) (time / Symbol.INTERVAL_DAY - dayFromZero);
		// if(day>0){
		String whatday = day == 0 ? "今天" : day == 1 ? "明天" : day == 2 ? "后天"
				: day + "天后";
		int hour = cltime.get(Calendar.HOUR_OF_DAY);
		int minute = cltime.get(Calendar.MINUTE);
		return whatday + " " + (hour > 9 ? hour : "0" + hour) + ":"
				+ (minute > 9 ? minute : "0" + minute);
		// }


	}

	private void drawTime(Graphics g) {
		// TODO Auto-generated method stub
		clipScreen();
		if (alarmState != ALARMSTATE_NOALARM) {
			mG.drawSystemString("下一次闹钟时间:", width / 2, (int) (height * 0.4));
			mG.drawSystemString(translateTimeToString(nextTime), width / 2,
					(int) (height * 0.6));
		} else {
			mG.drawSystemString("当前没有闹钟:", width / 2, (int) (height * 0.5));
		}
		// mG.drawBitmap(Bitmap_time, (int) (width / 2), (int) (height / 2),
		// mG.HCENTER | mG.VCENTER);

	}

	private void drawCircleAnim(Graphics mG2) {
		// TODO Auto-generated method stub
		int buf = stateLoop / cirAnimSpeed % I_cirAniCount;
		lastCircleAnimIndex = buf;
		if (!efficentMode || lastCircleAnimIndex != buf) {
			drawNewPage(mG);
			lastCircleAnimIndex = buf;
			clipScreen(ftio( circleSize));
			mG.drawBitmap(Bitmap_cirAnim[stateLoop / cirAnimSpeed
					% I_cirAniCount], (width / 2), height / 2, mG.HCENTER
					| mG.VCENTER);

		}
		timeLoopPlus();
	}

	private void drawText(Graphics g) {
		// TODO Auto-generated method stub

		Path a = new Path();

		RectF ef = new RectF(width / 2 - wholeSize / 2, height / 2 - wholeSize
				/ 2, width / 2 + wholeSize / 2, height / 2 + wholeSize / 2);

		a.addArc(ef, ftio ((currentAngle - 90 - arcAngle / 2)), arcAngle);
		g.drawArcText("NextAlarm", a, 0,
				ftio (width * SIZE_BORDER_CIRCILE / 2), textPaint);
	}

	private void updateLogic() {
		// TODO Auto-generated method stub
		// Log.e("boxGameView", "updateLogic start");

		float angle;
		targetAngle = changeTOVailid(targetAngle);
		currentAngle = changeTOVailid(currentAngle);
		angle = targetAngle - currentAngle;
		// if(currentAngle<targetAngle)
		// if (angle < 5 && angle > -5) {
		// currentAngle = targetAngle;
		// state = STATE_DONE;
		// return;
		// }
		currentAngle += pspeed;
		if (angle <= pspeed_abs && angle > -pspeed_abs) {
			// currentAngle += pspeed;
			pspeed *= -0.6;
			vibarate_count++;
			// return;
			if (vibarate_count == vibarate_Max) {
				currentAngle = targetAngle;
				state = STATE_DONE;
				vibarate_count = 0;
				return;
			}
		} else {
			vibarate_count = 0;
		}

		// Log.e("Current:" + currentAngle, "target:" + targetAngle);

	}

	private void drawNewPage(Graphics g) {
		// TODO Auto-generated method stub
		clipScreen( wholeSize);
		g.drawColor(Color.WHITE);
		g.drawBitmap2(Bitmap_cirBg, (width / 2), height / 2,ftio( circleSize),ftio(circleSize),mG.HCENTER
				| mG.VCENTER);
	} 

	private void drawRotate() {
		// clipScreen();
		mG.drawRotate(pspeed, width / 2, height / 2, arcPaint);
	}

	private void drawDone(Graphics g) {
		// TODO Auto-generated method stub
		Log.e("boxGameView", "drawDone");
		drawTime(g);
		drawGame2(g);
		drawText(g);

	}

	private void drawChangeing(Graphics g) {
		// clipScreen();

		// drawRotate();
		// Log.e("boxGameView", "drawChangeing");

	//	drawCircleAnim(g);
		drawText(g);
		drawGame2(g);
	}

	Xfermode mXfermode, mXfermode_buf;

	private void drawGame(Graphics g) {
		// TODO Auto-generated method stub

		clipScreen();
		arcPaint.setXfermode(mXfermode);
		mG.drawArcBySweep(width / 2, height / 2, ftio (wholeSize - 1),
				ftio (wholeSize - 1), 0, 360, arcPaint);

		clipScreen();
		int startAngle = ftio ((currentAngle - 90 - arcAngle / 2));
		if (state == STATE_DONE) {
			switch (alarmState) {
			case ALARMSTATE_NOALARM:
				arcPaint.setColor(Color.GRAY);
				break;
			case ALARMSTATE_SLEEPALARM:
				arcPaint.setColor(Color.RED);
				break;
			case ALARMSTATE_NORMAL:
				arcPaint.setColor(Color.RED | Color.GRAY);
				break;

			}
			// arcPaint.setColor(Color.GRAY);
			// //} else {
			// arcPaint.setColor(Color.RED | Color.GRAY);
		}
		arcPaint.setXfermode(mXfermode_buf);
		mG.drawArcBySweep(width / 2, height / 2, ftio (wholeSize - 1),
				ftio (wholeSize - 1), startAngle, arcAngle, arcPaint);

	}

	private void drawGame2(Graphics g) {
		// TODO Auto-generated method stub

		clipScreen();
		
		arcPaint.setXfermode(mXfermode);
		mG.drawArcBySweep(width / 2, height / 2, ftio (wholeSize - 1),
				ftio (wholeSize - 1), 0, 360, arcPaint);

		clipScreen();
		int startAngle = ftio ((currentAngle - 90 - arcAngle / 2));
		if (state == STATE_DONE) {
			switch (alarmState) {
			case ALARMSTATE_NOALARM:
				arcPaint.setColor(Color.GRAY);
				break;
			case ALARMSTATE_SLEEPALARM:
				arcPaint.setColor(Color.RED);
				break;
			case ALARMSTATE_NORMAL:
				arcPaint.setColor(Color.RED | Color.GRAY);
				break;

			}
			// arcPaint.setColor(Color.GRAY);
			// //} else {
			// arcPaint.setColor(Color.RED | Color.GRAY);
		}
		arcPaint.setXfermode(mXfermode_buf);
//		mG.drawArcBySweep(width / 2, height / 2, (int) (wholeSize - 1),
//				(int) (wholeSize - 1), startAngle, arcAngle, arcPaint);
		mG.drawRotate(currentAngle, width / 2, height / 2,arcPaint);
		mG.drawBitmap2(Bitmap_cirArrow, (width / 2), height / 2,ftio (wholeSize),ftio(wholeSize),mG.HCENTER
				| mG.VCENTER);

	}

	
	private float changeTOVailid(float targetAngle2) {
		while (targetAngle2 < 0) {
			targetAngle2 += 360;
		}
		while (targetAngle2 >= 360) {
			targetAngle2 -= 360;
		}
		return targetAngle2;

	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// TODO Auto-generated method stub
		Log.e("boxGameView", "surfaceChanged");
		this.width = width;
		this.height = height;

	}
	private int ftio(float f){
		return (int)(f+0.5f);
	}

	Object Lock;
	private TimerTask task;
	protected int currentIndex = -2;
	protected Long nextTime;

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		Log.e("boxGameView", "surfaceCreated");

		this.width = getWidth();
		this.height = getHeight();

		arcPaint = new Paint();
		arcPaint.setColor(color_alarm_special);
		arcPaint.setStyle(Paint.Style.STROKE);
		arcPaint.setStrokeWidth(width * SIZE_BORDER_CIRCILE);
		arcPaint.setAntiAlias(true);

		textPaint = new Paint();
		textPaint.setTextSize(width * SIZE_BORDER_CIRCILE / 2);
		textPaint.setTextAlign(Paint.Align.CENTER);
		textPaint.setColor(Color.BLACK);
		textPaint.setAntiAlias(true);

		mXfermode_buf = arcPaint.getXfermode();
		circleSize = (float) (height * SIZE_INNER_CIRCLE);
		fontSize = (float) (width * SIZE_INNER_CIRCLE / 8);
		wholeSize = (width * (SIZE_INNER_CIRCLE + SIZE_BORDER_CIRCILE)*1.01f);

		mG.setFont(Typeface.DEFAULT_BOLD, Style.FILL_AND_STROKE, Color.BLACK,
				fontSize);
		mXfermode = new PorterDuffXfermode(
				android.graphics.PorterDuff.Mode.CLEAR);

		DayChangeTimer = new Timer();
		task = new TimerTask() {
			public void run() {
				onAlarmChange(currentIndex, nextTime);
			}

		};
		DayChangeTimer.schedule(task, (System.currentTimeMillis()
				/ Symbol.INTERVAL_DAY + 1)
				* Symbol.INTERVAL_DAY, Symbol.INTERVAL_DAY);

		iniData();
		loadResource();
		inialOver = new Object();
		startGame();

	}

	private void startGame() {
		if (t == null || t.getState() == Thread.State.TERMINATED) {
			t = new Thread(this);
			t.start();
		} else
			synchronized (mSurfaceHolder) {
				if (t.getState() == Thread.State.WAITING) {

					mSurfaceHolder.notify();
				}
			}

	}

	Thread t;

	/**
	 * 初始化一些固定的参数
	 * 
	 * */
	private void iniData() {
		// currentIndex = -1;
		mLoop = true;
		stateLoop = 0;
		failCount = 0;
		playCount = 0;
		SLEEPTIME = ftio (200 * 5 / FPS);
		lastCircleAnimIndex = 0;
		arcAngle = 60;

	}

	private void loadResource() {
		b_right = Bitmap.createScaledBitmap(
				BitmapFactory.decodeResource(getResources(), R.drawable.lg),
				width, height, false);
		b_wrong = Bitmap.createScaledBitmap(
				BitmapFactory.decodeResource(getResources(), R.drawable.nr),
				width, height, false);
		b_win = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(
				getResources(), R.drawable.success), width, height, false);
		b_lose = Bitmap.createScaledBitmap(
				BitmapFactory.decodeResource(getResources(), R.drawable.fail),
				width, height, false);
		b_wait = Bitmap.createScaledBitmap(
				BitmapFactory.decodeResource(getResources(), R.drawable.fail),
				width, height, false);

		Bitmap_cirAnim = new Bitmap[2];
		Bitmap_cirAnim[0] = Bitmap.createScaledBitmap(BitmapFactory
				.decodeResource(getResources(), R.drawable.ciranim1),
				ftio (circleSize), ftio (circleSize), false);
		Bitmap_cirAnim[1] = Bitmap.createScaledBitmap(BitmapFactory
				.decodeResource(getResources(), R.drawable.ciranim2),
				ftio (circleSize), ftio (circleSize), false);
		Bitmap_cirBg= Bitmap.createBitmap(BitmapFactory
				.decodeResource(getResources(), R.drawable.innercircle));
		Bitmap_cirArrow = Bitmap.createBitmap(BitmapFactory
				.decodeResource(getResources(), R.drawable.circlearrow));
		
		
		I_cirAniCount = Bitmap_cirAnim.length;
		cirAnimFps = 5;
		cirAnimSpeed = FPS / cirAnimFps;

		Bitmap_time = Bitmap
				.createScaledBitmap(BitmapFactory.decodeResource(
						getResources(), R.drawable.circle), ftio (circleSize),
						ftio (circleSize), false);

	}

	private void timeLoopPlus() {
		stateLoop++;
	}

	/**
	 * 锁定整个能显示
	 * 
	 * */
	private void clipScreen() {
		mG.clipCircle(width / 2, height / 2, ftio (wholeSize / 2));
	}

	private void clipScreen(float size) {
		mG.clipRect(width / 2, width / 2,ftio (size / 2),ftio (size / 2));
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		mLoop = false;
		DayChangeTimer.cancel();
		inialOver = null;
	}

	float fontSize;// 字体的大小
	float wholeSize;
	float circleSize;

	int failCount;// 失败次数
	int playCount;// 游戏次数

	int stateLoop;
	int state;

	int currentColor;
	int textColor;
	int currentMode;

	private static int FPS = 30;
	private static final float default_FPS = 5;
	public static final int STATE_CHANGEING = 0;
	public static final int STATE_DONE = 1;

	private float currentAngle;
	private float targetAngle;

	public static float speed = 270;
	float pspeed;
	int arcAngle;

	private static final int COUNT_MAX_GAMELOOP = 4000;
	public static final int COUNT_MAX_RIGHTLOOP = 1000;
	public static final int COUNT_MAX_WRONGLOOP = 1000;
	private static final int COUNT_MAX_STARTLOOP = 100;
	private static final int ALARMSTATE_SLEEPALARM = 0;
	private static final int ALARMSTATE_NOALARM = 1;
	private static final int ALARMSTATE_NORMAL = 2;

	private static float SIZE_WHOLE = 1.0f;
	private static float SIZE_BORDER_CIRCILE = 0.3f;
	private static float SIZE_INNER_CIRCLE = 0.7f;

	Bitmap b_right, b_wrong, b_win, b_lose, b_wait;
	int alarmState;

	private boolean hasAvialableAlarm() {
		if (targetAngle == 0) {
			return false;
		}
		return true;
	}

	@Override
	public void onAlarmChange(int index, Long time) {
		// TODO Auto-generated method stub
		synchronized (mSurfaceHolder) {

			mSurfaceHolder.notify();
			nextTime = time;
			if (index == currentIndex) {
				// state = STAET_DONE;
				return;
			}
			currentIndex = index;

			if (index > 3) {
				state = STATE_CHANGEING;
			}
			switch (index) {
			case 0:
				index = 3;
				break;
			case 1:
				index = 0;
				break;
			case 3:
				index = 1;
				break;
			case 4:
				index = 2;
				break;
			}

			if (index > AlarmProvider.MAX_ALARM_COUNT - 1) {
				targetAngle = 0;
				alarmState = ALARMSTATE_SLEEPALARM;
			} else if (index == -1) {
				targetAngle = 0;
				alarmState = ALARMSTATE_NOALARM;
			} else {
				targetAngle = 45 + 90 * index;
				alarmState = ALARMSTATE_NORMAL;
			}
			float angle = changeTOVailid(targetAngle)
					- changeTOVailid(ftio( currentAngle));
			if (ftio (angle) == 0) {
				state = STATE_DONE;
				return;
			}
			if (angle > 180)
				targetAngle -= 360;
			else if (angle < -180)
				currentAngle -= 360;

			pspeed = (speed) / FPS * (targetAngle > currentAngle ? 1 : -1);
			pspeed_abs = Math.abs(pspeed);
			state = STATE_CHANGEING;

			targetAngle = changeTOVailid(targetAngle);
			currentAngle = changeTOVailid(ftio (currentAngle));

		}

	}

}
